Normally, any variable you use inside a useEffect must be added to the dependency array. If that variable changes frequently, your Effect re-runs constantly. useEffectEvent allows you to capture a value without making it a dependency. It solves stale closure issue without adding value to dependency array. useEffectEvent provides a stable function reference for use inside useEffect, allowing the function to always access the latest props and state without causing the effect to re-run when those values change.
useEffectEvent introduced in React 19.2 solves a long-standing problem: stale closures inside useEffect . Traditionally, if you needed to access a changing value (like theme) inside an effect without adding it to the dependency array, you'd risk accessing a stale value. If you added it to the array, the effect would re-run unnecessarily (e.g., causing a WebSocket to reconnect when a theme changes). useEffectEvent solves this by letting you split the 'event' part of the logic out of the effect that emits it .
useEffectEvent is used to create events which need to be called in effects(i.e. useEffect, useLayoutEffect, useInsertionEffect)
useEffectEvent lets you extract logic for event handlers which need to be called in an effect, uses reactive values but should not trigger a effect re-run and still needs access to the latest state or props.
In the corrected version, the onConnected function is created with useEffectEvent. It always reads the latest theme value, but its identity is stable, so it doesn't need to be in the useEffect dependency array. Changing the theme will no longer cause the chat to reconnect; it will simply be used in the next notification .
You need to call a function inside an effect (e.g., inside setInterval, an event listener, or a WebSocket callback).
That function needs to read the latest props or state without causing the effect to re-run when those values change .
You want to avoid adding unnecessary dependencies to your effect's dependency array, which can cause performance issues or unwanted side effects .
Stable Reference: The function returned by useEffectEvent has a stable identity and should not be added to dependency arrays . The ESLint plugin for React Hooks is updated to understand this and will warn if you try to add it .
Not for Render or JSX: useEffectEvent is strictly for functions called from within an effect. It cannot be called during rendering or passed directly to JSX as an event handler .
Not a Drop-in Replacement for useCallback: It solves a different problem. useCallback is for memoizing functions to prevent unnecessary re-renders of child components. useEffectEvent is for keeping functions inside effects stable .
In summary, useEffectEvent provides a clean, official solution to the 'stale closure' problem in useEffect. It simplifies code, improves performance by preventing unnecessary effect re-runs, and enhances clarity by explicitly separating 'events' from the effects that trigger them .